'''
Created on 2010-2-16

@author: summit
'''
import sys
from Stack import Stack
from LinkedList import LinkedList
from Iterator import Iterator
from Visitor import Visitor
from Exception import *

class StackAsLinkedList(Stack):
    '''
    Stack implemented using a linked list.
    '''


    def __init__(self):
        '''
        Constructs a stack.
        '''
        super(StackAsLinkedList, self).__init__()
        self._list = LinkedList()
    
    def purge(self):
        self._list.purge()
        self._count = 0
    
    def push(self, obj):
        self._list.prepend(obj)
        self._count += 1
    
    def pop(self):
        if self._count == 0:
            raise ContainerEmpty
        result = self._list.first.datum
        self._list.extract(result)
        self._count -= 1
        return result
    
    def getTop(self):
        if self._count == 0:
            raise ContainerEmpty
        return self._list.first.datum
    
    def accept(self, visitor):
        assert isinstance(visitor, Visitor)
        ptr = self._list.head
        while ptr is not None:
            visitor.visit(ptr.datum)
            if visitor.isDone:
                return
            ptr = ptr.next
    
    class Iterator(Iterator):
        
        def __init__(self, stack):
            super(StackAsLinkedList.Iterator, self).__init__(stack)
            self._position = stack._list.head
        
        def next(self):
            if self._position is None:
                raise StopIteration
            element = self._position
            self._position = self._position.next
            return element.datum
        
    def __iter__(self):
        return self.Iterator(self)
    
    def _compareTo(self, obj):
        assert isinstance(self, obj.__class__)
        raise NotImplementedError
    
    def main(*argv):
        "StackAsLinkedList test program."
        print StackAsLinkedList.main.__doc__
        stack2 = StackAsLinkedList()
        Stack.test(stack2)
        return 0
    main = staticmethod(main)

if __name__ == "__main__":
    sys.exit(StackAsLinkedList.main(*sys.argv))